import paddle
import paddle.nn as nn
import paddle.nn.functional as F
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import accuracy_score, f1_score, roc_auc_score, classification_report
from sklearn.impute import SimpleImputer  # 导入插补器
from imblearn.over_sampling import SMOTE  # 导入SMOTE
import matplotlib.pyplot as plt

# 确保PaddlePaddle处于动态图模式
paddle.disable_static()

# 加载数据集
data = pd.read_excel('E:\\2022040424 何欣 综合实践2\\11.23\data\高血压预测数据集.xlsx')

# 定义特征和标签
features = data.drop('高血压', axis=1).values
labels = data['高血压'].values

# 分割数据集为训练集和测试集
train_features, test_features, train_labels, test_labels = train_test_split(features, labels, test_size=0.4, random_state=42)

# 特征归一化
scaler = MinMaxScaler()
train_features_scaled = scaler.fit_transform(train_features)
test_features_scaled = scaler.transform(test_features)

# 使用SimpleImputer插补训练集中的缺失值
imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
train_features_scaled = imputer.fit_transform(train_features_scaled)

try:
    smote = SMOTE(random_state=42, k_neighbors=1)  # 设置最近邻的数量为1
    train_features_smote, train_labels_smote = smote.fit_resample(train_features_scaled, train_labels)
except ValueError as e:
    print(f"Error during oversampling: {e}")
    train_features_smote, train_labels_smote = train_features_scaled, train_labels

# 将过采样后的数据转换为paddle tensor
train_features_smote = paddle.to_tensor(train_features_smote, dtype='float32')
test_features_scaled = paddle.to_tensor(test_features_scaled, dtype='float32')
train_labels_smote = paddle.to_tensor(train_labels_smote.astype('float32'), dtype='float32').unsqueeze(1)
test_labels = paddle.to_tensor(test_labels.astype('float32'), dtype='float32').unsqueeze(1)

# 构建深度神经网络
class DNN(nn.Layer):
    def __init__(self):
        super(DNN, self).__init__()
        self.fc1 = nn.Linear(8, 64)  # 输入层到隐藏层
        self.fc2 = nn.Linear(64, 32)  # 隐藏层到隐藏层
        self.fc3 = nn.Linear(32, 1)  # 隐藏层到输出层

    def forward(self, x):
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = F.sigmoid(self.fc3(x))  # 使用sigmoid激活函数
        return x

# 初始化模型
model = DNN()

# 编译模型
optimizer = paddle.optimizer.Adam(parameters=model.parameters(), learning_rate=0.001)
loss_fn = nn.BCEWithLogitsLoss()




# 绘制特征重要性并保存图片
with paddle.no_grad():
    weights = model.fc1.weight.numpy()
    feature_importance = np.sum(np.abs(weights), axis=1)
    plt.figure(figsize=(10, 6))  # 可以设置图片大小
    plt.bar(range(len(feature_importance)), feature_importance)
    plt.xlabel('Features')
    plt.ylabel('Importance')
    plt.title('Feature Importance')
    plt.savefig('E:\\2022040424 何欣 综合实践2\\11.23\\ui_images\hypertension.png')  # 保存图片到image文件夹下
    plt.show()


# 预测函数，包括自定义阈值
def predict(model, features, threshold=0.5):
    features_scaled = scaler.transform(features)
    features_scaled = paddle.to_tensor(features_scaled, dtype='float32')

    model.eval()
    with paddle.no_grad():
        predictions = model(features_scaled)
        predictions = (predictions > threshold).astype('int32')

    return predictions.numpy()
paddle.save(model.state_dict(), 'E:\\2022040424 何欣 综合实践2\\11.23\\model\\hypertension_model.pdparams')